-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Turn eager normalization errors to delayed errors #82039
Conversation
r? @lcnr (rust-highfive has picked a reviewer for you, use r? to override) |
} | ||
} | ||
_ => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this actually reachable? Do we have a test case where hir::ItemKind::Union
ends up as ty::Error
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also curious about this. Was this getting hit? If not, can you revert?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, I added this because it is reached after removing the other ICE.
@@ -40,7 +41,13 @@ fn normalize_generic_arg_after_erasing_regions<'tcx>( | |||
debug_assert!(!erased.needs_infer(), "{:?}", erased); | |||
erased | |||
} | |||
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this bug
is quite valuable and helped us catch some bugs with const generics, so I would really like to keep it that way.
We pretty much only emit a bug here if the type is not well formed, and I think normalize_erasing_regions
should only be used on types that are well formed (even if there is another error).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having delay_span_bug
here should be fine. This mimics bug
with -Ztreat-err-as-bug
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We get there with const evaluatable bounds when emitting errors, but these errors should be silent when encountered during selection, so just always causing an ICE here is preferable for me.
We shouldn't hit this, even after having a compilation error. Having a delay_span_bug
here hides other bugs in the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We get there with const evaluatable bounds when emitting errors, but these errors should be silent when encountered during selection, so just always causing an ICE here is preferable for me.
I'm not sure I follow. Could you rephrase your position? It reads to me like
- We get there with const evaluatable bounds when emitting errors
- these errors should be silent when encountered during selection
- always causing an ICE here is preferable
means
- when we emit errors with const evaluatable bounds we get here
- trait selection should silence this errors
- we should always ICE when we hit these
which to me is saying two different things?
Would it be reasonable to only delay_span_bug
on stable/beta and make it bug!
in nightly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what @lcnr means is that the error we get here would be silenced by trait selection, but we don't want that and should ICE.
I would be extremely wary of having different behavior on stable vs nightly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We get there with const evaluatable bounds when emitting errors,
it is an implementation error for const evaluatable bounds to reach this bug!
and we still don't know all the places where this happens. Often when reaching this bug!
compilation would fail anyways so a delay_span_bug
would not trigger in these cases. That would mean that we would only get ICE here once they get triggered by const evaluatable bounds during selection (which then succeeds using a different candidate). This happens a lot less often though, so it would take us longer to find all of these cases. Does this make more sense this way?
.ty_adt_def() | ||
.map_or(false, |adt_def| adt_def.is_manually_drop()) | ||
&& !field_ty | ||
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the actual problem here. imo is_copy_modulo_regions
doesn't make sense outside of codegen/mir building.
This is currently a stability hole as the following compiles:
#[derive(Clone)]
struct Bar<'a>(&'a ());
impl Copy for Bar<'static> {}
union Foo<'a> {
field: u32,
other_field: Bar<'a>,
}
For some reason we also explicitly require types to be copy when initializing a union, so the following does error:
fn test<'a>(q: &'a ()) {
let bar = Bar(&q);
let foo: Foo<'a> = Foo {
other_field: bar,
};
}
Does using the following also fix this ICE?
let trait_ref = TraitRef::new(copy_def_id, tcx.intern_substs(&[field_ty.into()]));
let is_copy = tcx.infer_ctxt().enter(|infcx| {
infcx.predicate_must_hold_considering_regions(Obligation::new(
ObligationCause::dummy(),
param_env,
trait_ref.without_const().to_predicate(tcx),
))
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the root issue, but I agree that this seems like a potential soundness hole. I would maybe just file an issue for followup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the root issue
My understanding is that the root issue is calling codegen_fulfill_obligations
outside of codegen. I am a bit confused about why I said that is_copy_modulo_regions
is the issue here when there's a call to normailize_erasing_regions
right below it - as you've said in #82039 (comment). I personally prefer to "correctly" deal with regions in needs_drop
and similar methods, even if that is a more complex change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree. We shouldn't be erasing regions in needs_drop
and that is the more correct fix here.
☔ The latest upstream changes (presumably #81611) made this pull request unmergeable. Please resolve the merge conflicts. |
@estebank this is waiting for you to reply to the review and resolve the conflicts |
I am not able to review any PRs in the near future. I don't think there is anything a reviewer has to do for this PR right now |
ping again from triage: |
FYI, @jyn514 found a very small minimization in #87327 (comment) that may be useful as a test case: union U {
a: <Self as Iterator>::Item,
} |
r? @jackh726 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple comments but this looks good enough to me that I'm good with merging
} | ||
} | ||
_ => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also curious about this. Was this getting hit? If not, can you revert?
.ty_adt_def() | ||
.map_or(false, |adt_def| adt_def.is_manually_drop()) | ||
&& !field_ty | ||
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the root issue, but I agree that this seems like a potential soundness hole. I would maybe just file an issue for followup.
&& !field_ty | ||
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env) | ||
{ | ||
if field_ty.needs_drop(self.tcx, param_env) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, under the presumption that we should only be calling normalize_erasing_regions
on well-formed types, is the problem actually in needs_drop
...?
Here:
let subst_ty = tcx.normalize_erasing_regions( |
@@ -40,7 +41,13 @@ fn normalize_generic_arg_after_erasing_regions<'tcx>( | |||
debug_assert!(!erased.needs_infer(), "{:?}", erased); | |||
erased | |||
} | |||
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having delay_span_bug
here should be fine. This mimics bug
with -Ztreat-err-as-bug
right?
When normalizing `union`s with fields coming from associated types that don't satisfy trait bounds, avoid ICEing by using `delay_span_bug()` instead of `bug!()`. Fix rust-lang#81199.
triage:
setting to waiting on review |
Okay after the discussion in this thread, particularly with @lcnr, I'm now of mixed minds about this PR. Let me explain my thought process. First, as a bit of context to my thoughts, it's important to note that there are currently two real "ways" to normalize things: either through The current expectation here is that everything can get normalized in Another alternative is that the |
The issue was fixed with #91462. Closing this. |
When normalizing
union
s with fields coming from associated types thatdon't satisfy trait bounds, avoid ICEing by using
delay_span_bug()
instead of
bug!()
.Fix #81199.